package server

import (
	"net/http"
	"fmt"
	"encoding/json"
	"strconv"
	"strings"
	"github.com/pkg/errors"
	"io/ioutil"
	"io"
	"github.com/ingopansa/userinfoservice/model"
	"github.com/sirupsen/logrus"
)

func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
	start := s.now()
	t := s.now().Sub(start)

	err := func() error {
		// todo: implement logic for health checks

		return nil
	}()

	if err != nil {
		s.logger.Errorf("Storage health check failed: %v", err)
		renderError(s.logger, w, http.StatusInternalServerError, "Health check failed.")
		return
	}
	fmt.Fprintf(w, "Health check passed in %s", t)
}

func renderError(logger logrus.FieldLogger, w http.ResponseWriter, status int, description string) {
	logger.Debugf( "renderError(): description=%v", description)

	message, _ := json.Marshal(&map[string]string{"error": description,})
	w.WriteHeader(status)
	w.Write(message)
}

func renderResult(logger logrus.FieldLogger, w http.ResponseWriter, r *http.Request, obj interface{}){
	logger.Debugf( "renderResult()")

	if obj != nil {
		data, err := json.Marshal(obj)

		if err != nil {
			logger.Errorf("cannot marshal JSON")
			renderError(logger, w, http.StatusInternalServerError, "cannot marshal JSON")
		} else {
			w.Header().Set( "Content-Type", "application/json")
			w.Header().Set( "Content-Length", strconv.Itoa(len(data)))
			w.Write(data)
		}
	} else {
		w.Header().Set( "Content-Type", "text")
		w.WriteHeader(http.StatusOK)
	}
}

func (s *Server)handleListUsers(w http.ResponseWriter, r *http.Request){
	s.logger.Debugf("handleListUsers()")

	if users, err := s.storage.ListUsers(); err != nil {
		renderError(s.logger, w,http.StatusInternalServerError, fmt.Sprintf("error: %v", err))
	} else {
		renderResult(s.logger, w, r, users)
	}
}

func getAuthorizationBearer(rawAuthBearer string)(authBearer string, err error){
	// split the provided Authorization Header String
	if fields := strings.Fields(rawAuthBearer); len(fields) == 2 {
		return fields[1], nil
	}

	return authBearer, errors.New("Cannot split provided Authorization Bearer")
}



func (s *Server)handleAddUser(w http.ResponseWriter, r *http.Request){
	s.logger.Debugf("handleAddUser")
	var user model.User

	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := r.Body.Close(); err != nil {
		panic(err)
	}

	if err := json.Unmarshal(body, &user); err != nil {
		renderError(s.logger, w, http.StatusInternalServerError, "cannot unmarshal JSON")
	} else {
		if err := s.storage.AddUser(user); err != nil {
			renderError(s.logger, w, http.StatusInternalServerError, "cannot add user")
		} else {
			renderResult(s.logger, w,r,nil)
		}
	}
}